use std::rc::Rc;
use std::sync::OnceLock;

use bytes::Bytes;
use dioxus::prelude::*;
use fermi::AtomRoot;
use futures_util::stream::StreamExt;
use log::{error, info};
use reqwest::{Client, Method, Url};
use serde::Serialize;

use crate::error::Error::ResponseError;
use crate::error::Result;
use crate::ui::{unique_id, SETTINGS_BTN_DISABLE};

mod ali;
mod baidu;
mod config;
mod xun_fei;

pub static HTTP_CLIENT: OnceLock<Client> = OnceLock::new();
pub static HTTP_URL: OnceLock<Url> = OnceLock::new();

pub enum Api {
    ConfigReload,
    XfCorrection,
    XfProofreading,
    XfCompliance,
    BaiduCorrection,
    BaiduProofreading,
    AliCorrection,
}

pub async fn api_service(mut rx: UnboundedReceiver<Api>, atoms: Rc<AtomRoot>) {
    while let Some(msg) = rx.next().await {
        match msg {
            Api::ConfigReload => {
                if let Err(e) = config::reload().await {
                    error!("更新配置失败：{e}");
                } else {
                    info!("配置加载成功");
                    // atoms.set(unique_id(&INPUT_TEXT), true);
                }
                atoms.set(unique_id(&SETTINGS_BTN_DISABLE), false);
            }
            Api::XfCorrection => {
                //
            }
            Api::XfProofreading => {}
            Api::XfCompliance => {}
            Api::BaiduCorrection => {}
            Api::BaiduProofreading => {}
            Api::AliCorrection => {}
        }
    }
}

pub async fn http<Req: Serialize>(
    method: Method,
    path: &str,
    request: Option<&Req>,
) -> Result<Bytes> {
    let client = HTTP_CLIENT.get().unwrap();
    let url = HTTP_URL.get().and_then(|u| u.join(path).ok()).unwrap();

    // 发送请求
    let res = match request {
        Some(req) => client.request(method, url).json(req).send().await?,
        None => client.request(method, url).send().await?,
    };

    let status = res.status();
    let msg = res.bytes().await?;

    if !status.is_success() {
        return Err(ResponseError {
            status,
            msg: String::from_utf8_lossy(&msg).to_string(),
        });
    }

    Ok(msg)
}
